package android.microblog.Sina;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import weibo4andriod.Configuration;
import weibo4andriod.WeiboException;
import weibo4andriod.http.PostParameter;
import weibo4andriod.http.Response;
import weibo4andriod.org.json.JSONArray;
import weibo4andriod.org.json.JSONException;
import weibo4andriod.org.json.JSONObject;
import android.microblog.Abstract.MicroblogFactory;
import android.microblog.Abstract.MicroblogOAuth;
import android.microblog.Common.Util;
import android.microblog.Data.Comment;
import android.microblog.Data.Count;
import android.microblog.Data.DirectMessage;
import android.microblog.Data.PostInfo;
import android.microblog.Data.RateLimitStatus;
import android.microblog.Data.User;
import android.microblog.Interface.IMicroblogFactory;

public class SinaFactory extends MicroblogFactory {

	private static SinaFactory factoryInstance = null;

	synchronized public static IMicroblogFactory getInstance() {
		if (factoryInstance == null)
			factoryInstance = new SinaFactory();

		return factoryInstance;
	}

	private SinaOAuth authInstance = null;

	@Override
	public DirectMessage createDirectMsg(String id, String text) {
		try {
			return parseDirectMsg(SinaUtil.post(
					SinaUtil.getBaseURL() + "direct_messages/new.json",
					new PostParameter[] {
							new PostParameter("user_id", id),
							new PostParameter("text", text),
							new PostParameter("source", Configuration
									.getSource()) }, true).asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public PostInfo createFavorite(long id) {
		try {
			return parsePostInfo(SinaUtil.post(
					SinaUtil.getBaseURL() + "favorites/create/" + id + ".json",
					true).asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public User createFriendship(String id) {
		try {
			return parseUser(SinaUtil.post(
					SinaUtil.getBaseURL() + "friendships/create/" + id
							+ ".json", new PostParameter[0], true)
					.asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public DirectMessage destroyDirectMsg(long id) {
		try {
			return parseDirectMsg(SinaUtil.post(
					SinaUtil.getBaseURL() + "direct_messages/destroy/" + id
							+ ".json", new PostParameter[0], true)
					.asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<DirectMessage> destroyDirectMsgBatch(String ids) {
		try {
			return parseDirectMsgs(SinaUtil
					.post(
							SinaUtil.getBaseURL()
									+ "direct_messages/destroy_batch.json",
							new PostParameter[] { new PostParameter("ids", ids) },
							true));
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public PostInfo destroyFavorite(long id) {
		try {
			return parsePostInfo(SinaUtil
					.post(
							SinaUtil.getBaseURL() + "favorites/destroy/" + id
									+ ".json", true).asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<PostInfo> destroyFavoriteBatch(String ids) {
		try {
			return parsePostInfos(SinaUtil
					.post(
							SinaUtil.getBaseURL()
									+ "favorites/destroy_batch.json",
							new PostParameter[] { new PostParameter("ids", ids) },
							true));
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public User destroyFriendship(String id) {
		try {
			return parseUser(SinaUtil.post(
					SinaUtil.getBaseURL() + "friendships/destroy/" + id
							+ ".json", new PostParameter[0], true)
					.asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public User endSession() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "account/end_session.json", true);
			return parseUser(res.asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public boolean existsFriendship(String userA, String userB) {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "friendships/exists.json", new PostParameter[] {
					new PostParameter("user_a", userA),
					new PostParameter("user_b", userB) }, true);
			return res.asString().indexOf("true") != -1;
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	public List<Comment> getComments(String id) {

		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/comments.json?id={0}" + id, true);
			return parseComments(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<Comment> getCommentsByMe() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/comments_by_me.json", true);
			return parseComments(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<Comment> getCommentsTimeLine() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/comments_timeline.json", true);
			return parseComments(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<Comment> getCommentsToMe() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/comments_to_me.json", true);
			return parseComments(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<Count> getCounts() {
		/*
		 * try { Response res = SinaUtil.get(SinaUtil.getBaseURL() +
		 * "statuses/counts.json?ids=" + ids, true); return parseComment(res); }
		 * catch (WeiboException e) { e.printStackTrace(); }
		 */
		return null;
	}

	@Override
	public List<DirectMessage> getDirectMsgList() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "direct_messages.json", true);
			return parseDirectMsgs(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<DirectMessage> getDirectMsgSendList() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "direct_messages/sent.json", new PostParameter[0], true);
			return parseDirectMsgs(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<PostInfo> getFavoriteList() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "favorites.json", new PostParameter[0], true);
			return parsePostInfos(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<User> getFriendList() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/friends.json", true);
			return parseUsers(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<User> getFriendList(String id) {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/friends/" + id + ".json", false);
			return parseUsers(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<PostInfo> getFriendsTimeLine() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/friends_timeline.json", true);
			return parsePostInfos(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<PostInfo> getMentions() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/mentions.json", true);
			return parsePostInfos(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public MicroblogOAuth getOAuth() {
		if (authInstance == null)
			authInstance = new SinaOAuth();
		return authInstance;

	}

	@Override
	public List<PostInfo> getPublicTimeLine() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/public_timeline.json", true);
			return parsePostInfos(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public RateLimitStatus getRateLimitStatus() {
		// account/rate_limit_status.json
		return null;
	}

	@Override
	public List<PostInfo> getUserTimeLine() {
		try {
			Response res = SinaUtil.get(SinaUtil.getBaseURL()
					+ "statuses/user_timeline.json", true);
			return parsePostInfos(res);
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private Comment parseComment(JSONObject json) throws WeiboException {
		try {
			Comment comment = new Comment();
			comment.setId(json.getLong("id"));
			comment.setText(json.getString("text"));
			comment.setSource(json.getString("source"));
			comment.setCreatedAt(Util.parseDate(json.getString("created_at"),
					"EEE MMM dd HH:mm:ss z yyyy"));

			return comment;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private List<Comment> parseComments(Response res) throws WeiboException {
		try {
			JSONArray list = res.asJSONArray();
			int size = list.length();
			List<Comment> comments = new ArrayList<Comment>(size);
			for (int i = 0; i < size; i++) {
				comments.add(parseComment(list.getJSONObject(i)));
			}
			return comments;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private DirectMessage parseDirectMsg(JSONObject json) throws WeiboException {
		try {
			DirectMessage directMsg = new DirectMessage();
			directMsg.setId(json.getInt("id"));
			directMsg.setText(json.getString("text"));
			directMsg.setSender_id(json.getInt("sender_id"));
			directMsg.setRecipient_id(json.getInt("recipient_id"));
			directMsg
					.setCreated_at(Util.parseDate(json.getString("created_at"),
							"EEE MMM dd HH:mm:ss z yyyy"));
			directMsg.setSender_screen_name(json
					.getString("sender_screen_name"));
			directMsg.setRecipient_screen_name(json
					.getString("recipient_screen_name"));

			/*
			 * if(!json.isNull("sender")) sender = new
			 * User(json.getJSONObject("sender"));
			 */
		} catch (JSONException jsone) {
			throw new WeiboException(
					jsone.getMessage() + ":" + json.toString(), jsone);
		}
		return null;
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private List<DirectMessage> parseDirectMsgs(Response res)
			throws WeiboException {
		try {
			JSONArray list = res.asJSONArray();
			int size = list.length();
			List<DirectMessage> directMsgs = new ArrayList<DirectMessage>(size);
			for (int i = 0; i < size; i++) {
				directMsgs.add(parseDirectMsg(list.getJSONObject(i)));
			}
			return directMsgs;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	/**
	 * @param list
	 * @param postInfos
	 * @param i
	 * @return
	 * @throws JSONException
	 * @throws WeiboException
	 */
	private PostInfo parsePostInfo(JSONObject json) throws WeiboException {
		try {
			PostInfo postInfo = new PostInfo();
			postInfo.setId(json.getLong("id"));
			postInfo.setText(json.getString("text"));
			postInfo.setSource(json.getString("source"));
			postInfo.setCreatedAt(Util.parseDate(json.getString("created_at"),
					"EEE MMM dd HH:mm:ss z yyyy"));

			return postInfo;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private List<PostInfo> parsePostInfos(Response res) throws WeiboException {
		try {
			JSONArray list = res.asJSONArray();
			int size = list.length();
			List<PostInfo> postInfos = new ArrayList<PostInfo>(size);
			for (int i = 0; i < size; i++) {
				postInfos.add(parsePostInfo(list.getJSONObject(i)));
			}
			return postInfos;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private User parseUser(JSONObject json) throws WeiboException {
		try {

			User user = new User();
			user.setId(json.getInt("id"));
			user.setName(json.getString("name"));
			user.setScreenName(json.getString("screen_name"));
			user.setLocation(json.getString("location"));
			user.setDescription(json.getString("description"));
			user.setProfileImageUrl(json.getString("profile_image_url"));
			user.setUrl(json.getString("url"));
			user.setIsProtected(json.getBoolean("protected"));
			user.setFollowersCount(json.getInt("followers_count"));

			user.setProfileBackgroundColor(json
					.getString("profile_background_color"));
			user.setProfileTextColor(json.getString("profile_text_color"));
			user.setProfileLinkColor(json.getString("profile_link_color"));
			user.setProfileSidebarFillColor(json
					.getString("profile_sidebar_fill_color"));
			user.setProfileSidebarBorderColor(json
					.getString("profile_sidebar_border_color"));
			user.setFriendsCount(json.getInt("friends_count"));
			user.setCreatedAt(Util.parseDate(json.getString("created_at"),
					"EEE MMM dd HH:mm:ss z yyyy"));
			user.setFavouritesCount(json.getInt("favourites_count"));
			user.setUtcOffset(json.getInt("utc_offset"));
			user.setTimeZone(json.getString("time_zone"));
			user.setProfileBackgroundImageUrl(json
					.getString("profile_background_image_url"));
			user.setProfileBackgroundTile(json
					.getString("profile_background_tile"));
			user.setFollowing(json.getBoolean("following"));
			user.setNotificationEnabled(json.getBoolean("notifications"));
			user.setStatusesCount(json.getInt("statuses_count"));

			return user;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	/**
	 * @param res
	 * @return
	 * @throws WeiboException
	 */
	private List<User> parseUsers(Response res) throws WeiboException {
		try {
			JSONArray list = res.asJSONArray();
			int size = list.length();
			List<User> users = new ArrayList<User>(size);
			for (int i = 0; i < size; i++) {
				users.add(parseUser(list.getJSONObject(i)));
			}
			return users;
		} catch (JSONException jsone) {
			throw new WeiboException(jsone);
		} catch (WeiboException te) {
			throw te;
		}
	}

	@Override
	public User updateProfile(String name, String email, String url,
			String location, String description) {
		List<PostParameter> profile = new ArrayList<PostParameter>(5);
		SinaUtil.addParameterToList(profile, "name", name);
		SinaUtil.addParameterToList(profile, "email", email);
		SinaUtil.addParameterToList(profile, "url", url);
		SinaUtil.addParameterToList(profile, "location", location);
		SinaUtil.addParameterToList(profile, "description", description);

		try {
			return parseUser(SinaUtil.post(
					SinaUtil.getBaseURL() + "account/update_profile.json",
					profile.toArray(new PostParameter[profile.size()]), true)
					.asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public User updateProfileColors(String profileBackgroundColor,
			String profileTextColor, String profileLinkColor,
			String profileSidebarFillColor, String profileSidebarBorderColor) {
		List<PostParameter> colors = new ArrayList<PostParameter>(5);
		SinaUtil.addParameterToList(colors, "profile_background_color",
				profileBackgroundColor);
		SinaUtil.addParameterToList(colors, "profile_text_color",
				profileTextColor);
		SinaUtil.addParameterToList(colors, "profile_link_color",
				profileLinkColor);
		SinaUtil.addParameterToList(colors, "profile_sidebar_fill_color",
				profileSidebarFillColor);
		SinaUtil.addParameterToList(colors, "profile_sidebar_border_color",
				profileSidebarBorderColor);
		try {
			return parseUser(SinaUtil.post(
					SinaUtil.getBaseURL()
							+ "account/update_profile_colors.json",
					colors.toArray(new PostParameter[colors.size()]), true)
					.asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public User updateProfileImage(File image) {
		try {
			return parseUser(SinaUtil
					.multPartURL(
							"image",
							SinaUtil.getBaseURL()
									+ "account/update_profile_image.json",
							null, image, true).asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public User verifyCredentials() {
		try {
			return parseUser(SinaUtil.get(
					SinaUtil.getBaseURL() + "account/verify_credentials.json",
					true).asJSONObject());
		} catch (WeiboException e) {
			e.printStackTrace();
		}
		return null;
	}
}
